/*
 * Jenny Ruppen 09-730-391
 * Sebastien Goldberg 08-914-855
 * Henry Raymond 08-928-061
 * Stefan Mussato 09-752-270
 */
 
package ch.uzh.ifi.sopra.gruppe9.game;

import java.util.ArrayList;
import com.jme3.scene.Node;


/**
 * Screen displaying text input field asking player to enter host for connection.
 */
public class ConnectionScreen extends Node implements IUpdatable {
	
	
	/**
	 * List of all registered mouseOver event elements of the connection screen.
	 */
	private ArrayList<IMouseOverable> mouseOverables = new ArrayList<IMouseOverable>();
	
	
	/**
	 * List of all registered click event elements of the connection screen.
	 */
	private ArrayList<IClickable> clickables = new ArrayList<IClickable>();
	
	
	/**
	 * List of all registered mouseOver event elements of the error screen.
	 */
	private ArrayList<IMouseOverable> errorMouseOverables = new ArrayList<IMouseOverable>();
	
	
	/**
	 * List of all registered click event elements of the error screen.
	 */
	private ArrayList<IClickable> errorClickables = new ArrayList<IClickable>();
	
	
	/**
	 * Geometry node of background, logo and credits
	 */
	private Node baseGeometry;
	
	
	/**
	 * Text input field for host address.
	 */
	private GuiTextInput input;
	
	
	/**
	 * Window around input field.
	 */
	private GuiWindow window;
	
	
	/**
	 * Waiting wheel.
	 */
	private GuiWaiting waiting;
	
	
	/**
	 * Text asking player to enter host.
	 */
	private GuiText enterHostText;
	
	
	/**
	 * Text showed while waiting for connection.
	 */
	private GuiText connectingText;
	
	
	/**
	 * Connect button.
	 */
	private GuiButton button;
	
	
	/**
	 * Text containing error message if error occurred.
	 */
	private GuiText errorText;
	
	
	/**
	 * OK button if error occurred.
	 */
	private GuiButton errorButton;
	
	
	/**
	 * Window displayed if error occurred.
	 */
	private GuiWindow errorWindow;
	
	
	
	/**
	 * Current state of the connection screen.
	 */
	private GuiState.State state;
	
	
	/**
	 * Countdown before connection is started to create a fake sense of long connection time.
	 */
	private float connectionCountdown;
	
	
	/**
	 * Constructor: Creates geometry.
	 */
	public ConnectionScreen() {
		
		// base geometry
		
		baseGeometry = new Node();
		
		GuiQuad background = new GuiQuad();
		background.setPositionSize(GUI.Offset.WINDOW, 0, 0, GUI.getScaledWindowWidth(), 768, 0);
		background.setMaterial(MaterialManager.getMarble(), 0.0f, 0.0f, 0.0019531275f * GUI.getScaledWindowWidth(), 1.5f);
		baseGeometry.attachChild(background.create());
		
		GuiQuad logo = new GuiQuad();
		logo.setPositionSize(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() / 2) - 160, 0, 320, 240, 1);
		logo.setMaterial(MaterialManager.getLogo(), 0.0f, 0.0f, 1.0f, 1.0f);
		baseGeometry.attachChild(logo.create());
		
		GuiText credits1 = new GuiText("S\u00E9bastien Goldberg,  Stefan Mussato,  Henry Raymond  &  Jenny Ruppen.", Fonts.getSmall());
		credits1.setPositionSize(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() - (int)credits1.getLineWidth()) / 2, 730, 1);
		baseGeometry.attachChild(credits1);
        
		GuiText credits2 = new GuiText("Software Praktikum, Universit\u00E4t Z\u00FCrich, 2012", Fonts.getSmall());
		credits2.setPositionSize(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() - (int)credits2.getLineWidth()) / 2, 747, 1);
		baseGeometry.attachChild(credits2);
		
		
		// connection screen
		
		ICallback submitFunction = new ICallback() { 
			public void run() { 
				GUI.changeState(GuiState.State.WAITING_FOR_CONNECTION);
			}
		};
		
		enterHostText = new GuiText("Gib bitte den Host des Spiels an:");
		enterHostText.setPositionSize(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() - (int)enterHostText.getLineWidth()) / 2, 370, 2);
        
		input = new GuiTextInput("127.0.0.1");
		input.setPositionSize(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() / 2) - 135, 400, 270, 2);
		input.setAction(submitFunction);
		input.create();
        
		button = new GuiButton("Verbinden");
		button.setPositionSize(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() / 2) - 100, 480, 200, 2);
		button.setAction(submitFunction);
		button.create();
		
		mouseOverables.add(button);
		
		clickables.add(input);
		clickables.add(button);
		
		window = new GuiWindow(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() / 2) - 215, 325, 430, 240, 1);
		
		
		// waiting for connection
		
		connectingText = new GuiText("Verbindung wird aufgebaut...");
		connectingText.setPositionSize(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() - (int)connectingText.getLineWidth()) / 2, 480, 1);
		
		waiting = new GuiWaiting(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() / 2) - 40, 380, 80, 1);
		
		
		// error occurred
		
		errorText = new GuiText("");
        
		errorButton = new GuiButton("OK");
		errorButton.setPositionSize(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() / 2) - 100, 450, 200, 2);
		errorButton.setAction(new ICallback() { 
			public void run() { 
				GUI.changeState(GuiState.State.CONNECTION_SCREEN);
			}
		});
		errorButton.create();
		
		errorWindow = new GuiWindow(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() / 2) - 300, 350, 600, 185, 1);
		
		
		errorMouseOverables.add(errorButton);
		
		errorClickables.add(errorButton);
	}
	
	
	/**
	 * Attach all needed geometry and register all mouseOver and click events.
	 */
	public void show(GuiState.State state) {
		this.state = state;
		
		this.attachChild(baseGeometry);
		
		if(state == GuiState.State.CONNECTION_SCREEN) {
			this.attachChild(enterHostText);
			this.attachChild(input);
			this.attachChild(button);
			this.attachChild(window);
			GUI.registerMouseOverable(mouseOverables);
			GUI.registerClickable(clickables);
			
		} else if(state == GuiState.State.WAITING_FOR_CONNECTION) {
			this.attachChild(waiting);
			this.attachChild(connectingText);
			connectionCountdown = 1.5f;
			GUI.registerUpdatable(waiting);
			GUI.registerUpdatable(this);
			
		} else if(state == GuiState.State.CONNECTION_FAILURE) {
			if(Connection.getError() == Connection.Error.COULD_NOT_CONNECT) {
				errorText.setText("Konnte nicht verbinden mit: " + input.getValue());
			} else if(Connection.getError() == Connection.Error.FOUR_PLAYERS) {
				errorText.setText("Es sind schon vier Spieler auf diesem Server.");
			} else if(Connection.getError() == Connection.Error.GAME_STARTED) {
				errorText.setText("Das Spiel auf diesem Server hat schon begonnen.");
			}
			errorText.setPositionSize(GUI.Offset.WINDOW, (GUI.getScaledWindowWidth() - (int)errorText.getLineWidth()) / 2, 390, 2);
			this.attachChild(errorText);
			this.attachChild(errorButton);
			this.attachChild(errorWindow);
			GUI.registerMouseOverable(errorMouseOverables);
			GUI.registerClickable(errorClickables);
		}
	}
	
	
	/**
	 * Detach all geometry and unregister all mouseOver and click events.
	 */
	public void hide() {
		
		this.detachChild(baseGeometry);
		
		if(state == GuiState.State.CONNECTION_SCREEN) {
			this.detachChild(enterHostText);
			input.stop();
			this.detachChild(input);
			this.detachChild(button);
			this.detachChild(window);
			GUI.unregisterMouseOverable(mouseOverables);
			GUI.unregisterClickable(clickables);
			
		} else if(state == GuiState.State.WAITING_FOR_CONNECTION) {
			this.detachChild(waiting);
			this.detachChild(connectingText);
			GUI.unregisterUpdatable(waiting);
			GUI.unregisterUpdatable(this);
			
		} else if(state == GuiState.State.CONNECTION_FAILURE) {
			this.detachChild(errorText);
			this.detachChild(errorButton);
			this.detachChild(errorWindow);
			GUI.unregisterMouseOverable(errorMouseOverables);
			GUI.unregisterClickable(errorClickables);
		}
	}


	@Override
	public void update(float delta) {
		connectionCountdown -= delta;
		if(connectionCountdown < 0.0f) {
			GUI.unregisterUpdatable(this);
			Connection.connect(input.getValue());
		}
	}
	
}
